package com.oa.hyperion.utils;

import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.exceptions.JWTVerificationException;
import com.auth0.jwt.interfaces.Claim;
import com.auth0.jwt.interfaces.DecodedJWT;
import com.oa.hyperion.exception.http.UnauthorizedException;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

/**
 * @author Liu
 * @date 2022年01月17日 11:59
 */
@Component
public class JwtUtils {
    private static String jwtKey;
    private static Integer expireTimeIn; //过期时间间隔

    public static Integer getId(String bearerToken) {
        String[] s = bearerToken.split(" ");
        if (s.length < 2) {
            throw new UnauthorizedException(30001);
        }
        Map<String, Claim> claim = getClaim(s[1]);
        if (claim == null) {
            throw new UnauthorizedException(30001);
        }
        return claim.get("id").asInt();
    }

    @Value("${hyperion.security.jwt-token}")
    public void setJwtKey(String jwtKey) {
        JwtUtils.jwtKey = jwtKey;
    }
    @Value("${hyperion.security.token-expired-in}")
    public void setExpireTimeIn(Integer expireTimeIn) {
        JwtUtils.expireTimeIn = expireTimeIn;
    }


    /**
     * @param id 用户的ID
     * @return 根据用户的ID生成jwt
     */
    public static String createJwt(int id) {
        System.out.println(jwtKey);
        Algorithm algorithm = Algorithm.HMAC256(jwtKey);
        Map<String, Date> mapTime = calculateExpiresTime();
        return JWT.create().withClaim("id", id)
                .withExpiresAt(mapTime.get("expire"))
                .withIssuedAt(mapTime.get("create"))
                .sign(algorithm);
    }

    /**
     * @return 返回一个map，包括创建的时间和到期的时间
     */
    private static Map<String, Date> calculateExpiresTime() {
        Map<String, Date> map = new HashMap<>();
        Calendar calendar = Calendar.getInstance();
        Date createTime = calendar.getTime();
        calendar.add(Calendar.SECOND, expireTimeIn);
        Date expireTime = calendar.getTime();
        map.put("create", createTime);
        map.put("expire", expireTime);
        return map;
    }


    /**
     * @param token 接收到的jwt
     * @return 如果是jwt可用返回true,否则返回false
     */
    public static Boolean verifyToken(String token) {
        try {
            Algorithm algorithm = Algorithm.HMAC256(jwtKey);
            JWTVerifier verifier = JWT.require(algorithm).build();
            verifier.verify(token);
        } catch (JWTVerificationException e) {
            return false;
        }
        return true;
    }


    /**
     * @param token 接收到的jwt
     * @return 返回一个map 通过key获取Claim对象，使用Claim对象的方法获得值.
     * 例如 :
     * Claim claim = map.get("id);
     * Integer id = claim.asInt();
     */
    public static Map<String, Claim> getClaim(String token) {
        DecodedJWT decodedJWT;
        Algorithm algorithm = Algorithm.HMAC256(jwtKey);
        JWTVerifier verifier = JWT.require(algorithm).build();
        try {
            decodedJWT = verifier.verify(token);
        } catch (JWTVerificationException e) {
            return null;
        }
        return decodedJWT.getClaims();
    }



}
